#ifndef FSM_AUTOBOILERSM_H
#define FSM_AUTOBOILERSM_H


#include "fsm.h"

//AutoBoilerSM_h_global_start
//Put_your_customer_code_here
#include "solenoid_valve_driver/solenoid_valve_driver.hpp"
#include "tim/pwm_generator.hpp"
//AutoBoilerSM_h_global_end

class AutoBoilerSM : public FSM {

//AutoBoilerSM_h_class_start
//Put_your_customer_code_here
public:
    AutoBoilerSM() : FSM(state_standby), fsm_instance_name("ABSM") {}

protected:
#define STEER_ANGLE_OFF     500
#define STEER_ANGLE_ON      2000
    SoleniodValveDriver soleniod_valve_driver{GPIOA, GPIO_PIN_6};
    PwmGenerator steer_engine{&htim4, TIM_CHANNEL_1};
//AutoBoilerSM_h_class_end

public:

void overwrite_entry_of_state_standby(const std::function<void()>& entry) {
    state_standby.entry = entry;
}
void overwrite_exit_of_state_standby(const std::function<void()>& exit) {
    state_standby.exit = exit;
}
void overwrite_entry_of_state_watering(const std::function<void()>& entry) {
    state_watering.entry = entry;
}
void overwrite_exit_of_state_watering(const std::function<void()>& exit) {
    state_watering.exit = exit;
}
void overwrite_entry_of_state_boiling(const std::function<void()>& entry) {
    state_boiling.entry = entry;
}
void overwrite_exit_of_state_boiling(const std::function<void()>& exit) {
    state_boiling.exit = exit;
}
void overwrite_entry_of_state_full(const std::function<void()>& entry) {
    state_full.entry = entry;
}
void overwrite_exit_of_state_full(const std::function<void()>& exit) {
    state_full.exit = exit;
}
void overwrite_entry_of_state_failure(const std::function<void()>& entry) {
    state_failure.entry = entry;
}
void overwrite_exit_of_state_failure(const std::function<void()>& exit) {
    state_failure.exit = exit;
}
void state_register() {
    state_standby.name = "state_standby";
    state_standby.entry = [this]{state_standby_entry();};
    state_standby.exit = [this]{state_standby_exit();};
    state_standby.events[t_watering] = [this]{transit(state_watering);};
    state_standby.events[t_full] = [this]{transit(state_full);};
    
    state_watering.name = "state_watering";
    state_watering.entry = [this]{state_watering_entry();};
    state_watering.exit = [this]{state_watering_exit();};
    state_watering.events[t_boiling] = [this]{transit(state_boiling);};
    state_watering.events[t_standby] = [this]{transit(state_standby);};
    
    state_boiling.name = "state_boiling";
    state_boiling.entry = [this]{state_boiling_entry();};
    state_boiling.exit = [this]{state_boiling_exit();};
    state_boiling.events[t_full] = [this]{transit(state_full);};
    state_boiling.events[t_standby] = [this]{transit(state_standby);};
    
    state_full.name = "state_full";
    state_full.entry = [this]{state_full_entry();};
    state_full.exit = [this]{state_full_exit();};
    state_full.events[t_standby] = [this]{transit(state_standby);};
    
    state_failure.name = "state_failure";
    state_failure.entry = [this]{state_failure_entry();};
    state_failure.exit = [this]{state_failure_exit();};
    state_failure.events[t_standby] = [this]{transit(state_standby);};
    
}

void start() override {
    enter_initial_state();
}


const std::string t_watering = "t_watering";
const std::string t_full = "t_full";
const std::string t_boiling = "t_boiling";
const std::string t_standby = "t_standby";

private:

//AutoBoilerSM_cpp_global_start
//Put_your_customer_code_here
//AutoBoilerSM_cpp_global_end


void state_standby_entry() {
    CCLOG(SWEN_INFO, "%s enter state standby", fsm_instance_name.c_str());
//Standby_entry_start
//Put_your_customer_code_here
    soleniod_valve_driver.set_off();
    steer_engine.init();
    steer_engine.set_duty(STEER_ANGLE_OFF);
//Standby_entry_end
}

void state_standby_exit() {
    CCLOG(SWEN_INFO, "%s exit  state standby", fsm_instance_name.c_str());
//Standby_exit_start
//Put_your_customer_code_here
//Standby_exit_end
}

void state_watering_entry() {
    CCLOG(SWEN_INFO, "%s enter state watering", fsm_instance_name.c_str());
//Watering_entry_start
//Put_your_customer_code_here
    soleniod_valve_driver.set_on();
//Watering_entry_end
}

void state_watering_exit() {
    CCLOG(SWEN_INFO, "%s exit  state watering", fsm_instance_name.c_str());
//Watering_exit_start
//Put_your_customer_code_here
//Watering_exit_end
}

void state_boiling_entry() {
    CCLOG(SWEN_INFO, "%s enter state boiling", fsm_instance_name.c_str());
//Boiling_entry_start
//Put_your_customer_code_here
    steer_engine.set_duty(STEER_ANGLE_ON);
//Boiling_entry_end
}

void state_boiling_exit() {
    CCLOG(SWEN_INFO, "%s exit  state boiling", fsm_instance_name.c_str());
//Boiling_exit_start
//Put_your_customer_code_here
    steer_engine.set_duty(STEER_ANGLE_OFF);
//Boiling_exit_end
}

void state_full_entry() {
    CCLOG(SWEN_INFO, "%s enter state full", fsm_instance_name.c_str());
//Full_entry_start
//Put_your_customer_code_here
    soleniod_valve_driver.set_off();
//Full_entry_end
}

void state_full_exit() {
    CCLOG(SWEN_INFO, "%s exit  state full", fsm_instance_name.c_str());
//Full_exit_start
//Put_your_customer_code_here
//Full_exit_end
}

void state_failure_entry() {
    CCLOG(SWEN_INFO, "%s enter state failure", fsm_instance_name.c_str());
//Failure_entry_start
//Put_your_customer_code_here
    soleniod_valve_driver.set_off();
//Failure_entry_end
}

void state_failure_exit() {
    CCLOG(SWEN_INFO, "%s exit  state failure", fsm_instance_name.c_str());
//Failure_exit_start
//Put_your_customer_code_here
//Failure_exit_end
}



    
    FSM::State state_standby;
    FSM::State state_watering;
    FSM::State state_boiling;
    FSM::State state_full;
    FSM::State state_failure;
    const std::string fsm_instance_name;
};

#endif